package cn.song.freight.enums;

import lombok.Getter;

import java.util.HashMap;
import java.util.Map;

/**
 * 地区层级枚举
 * <pre>
 * 该枚举定义了系统支持的地区层级类型，用于替代硬编码的数字常量。
 * 
 * 支持的层级类型：
 * 1. 省级（PROVINCE）：省份、直辖市、自治区、特别行政区
 *    - 适用场景：省级运费策略配置
 *    - 特点：最高层级，覆盖范围最广
 * 
 * 2. 市级（CITY）：地级市、区县级市、州、盟等
 *    - 适用场景：城市级运费策略配置
 *    - 特点：中等层级，城市范围内配置
 * 
 * 3. 区县级（DISTRICT）：区、县、县级市等
 *    - 适用场景：精确的区县级运费策略配置
 *    - 特点：最精细层级，配置精度最高
 * </pre>
 *
 * @author SongRenShuo
 * @version 3.0.0
 * @since 2025-08-28
 */
@Getter
public enum AreaLevel {
    
    /**
     * 省级（层级1）
     * <p>
     * 包括省份、直辖市、自治区、特别行政区等：
     * - 省份：如广东省、山东省等
     * - 直辖市：如北京市、上海市、天津市、重庆市
     * - 自治区：如新疆维吾尔自治区、西藏自治区等
     * - 特别行政区：如香港特别行政区、澳门特别行政区
     */
    PROVINCE(1, "省级", "省份、直辖市、自治区、特别行政区"),
    
    /**
     * 市级（层级2）
     * <p>
     * 包括地级市、区县级市、州、盟等：
     * - 地级市：如广州市、深圳市、青岛市等
     * - 区县级市：如县级市
     * - 州：如延边朝鲜族自治州等
     * - 盟：如内蒙古的盟
     */
    CITY(2, "市级", "地级市、区县级市、州、盟等"),
    
    /**
     * 区县级（层级3）
     * <p>
     * 包括区、县、县级市等：
     * - 市辖区：如天河区、朝阳区等
     * - 县：如番禺县、从化县等
     * - 县级市：如增城市等
     * - 其他县级行政区：如旗、自治县等
     */
    DISTRICT(3, "区县级", "区、县、县级市等县级行政区");
    
    /**
     * 层级代码
     */
    private final Integer code;
    
    /**
     * 层级名称
     */
    private final String name;
    
    /**
     * 层级描述
     */
    private final String description;
    
    /**
     * 代码到名称的映射缓存
     */
    private static final Map<Integer, String> CODE_TO_NAME_MAP = new HashMap<>();
    
    /**
     * 名称到代码的映射缓存
     */
    private static final Map<String, Integer> NAME_TO_CODE_MAP = new HashMap<>();
    
    /**
     * 构造函数
     *
     * @param code 层级代码
     * @param name 层级名称
     * @param description 层级描述
     */
    AreaLevel(Integer code, String name, String description) {
        this.code = code;
        this.name = name;
        this.description = description;
    }
    
    /**
     * 通过 code 获取 name
     *
     * @param code 层级编码
     * @return 对应的名称
     */
    public static String getNameByCode(Integer code) {
        if (code == null) {
            return "未知";
        }
        // 缓存为空时，初始化缓存
        if (CODE_TO_NAME_MAP.isEmpty()) {
            for (AreaLevel level : values()) {
                CODE_TO_NAME_MAP.put(level.getCode(), level.getName());
            }
        }
        return CODE_TO_NAME_MAP.getOrDefault(code, "未知");
    }
    
    /**
     * 通过 name 获取 code
     *
     * @param name 层级名称
     * @return 对应的code
     */
    public static Integer getCodeByName(String name) {
        if (name == null) {
            return 0;
        }
        // 缓存为空时，初始化缓存
        if (NAME_TO_CODE_MAP.isEmpty()) {
            for (AreaLevel level : values()) {
                NAME_TO_CODE_MAP.put(level.getName(), level.getCode());
            }
        }
        return NAME_TO_CODE_MAP.getOrDefault(name, 0);
    }
    
    /**
     * 根据代码查找对应的地区层级枚举
     *
     * @param code 层级代码
     * @return 对应的枚举值
     * @throws IllegalArgumentException 当代码无效时抛出
     */
    public static AreaLevel fromCode(Integer code) {
        if (code == null) {
            throw new IllegalArgumentException("层级代码不能为null");
        }
        for (AreaLevel level : values()) {
            if (level.code.equals(code)) {
                return level;
            }
        }
        throw new IllegalArgumentException("不支持的地区层级代码: " + code);
    }
    
    /**
     * 根据代码查找对应的地区层级枚举（安全版本）
     *
     * @param code 层级代码
     * @return 对应的枚举值，如果未找到则返回null
     */
    public static AreaLevel fromCodeSafe(Integer code) {
        if (code == null) {
            return null;
        }
        for (AreaLevel level : values()) {
            if (level.code.equals(code)) {
                return level;
            }
        }
        return null;
    }
    
    /**
     * 检查指定的代码是否为有效的地区层级
     *
     * @param code 要检查的代码
     * @return 如果代码有效返回true，否则返回false
     */
    public static boolean isValidCode(Integer code) {
        return fromCodeSafe(code) != null;
    }
    
    /**
     * 检查当前层级是否为省级
     *
     * @return 如果是省级返回true，否则返回false
     */
    public boolean isProvince() {
        return this == PROVINCE;
    }
    
    /**
     * 检查当前层级是否为市级
     *
     * @return 如果是市级返回true，否则返回false
     */
    public boolean isCity() {
        return this == CITY;
    }
    
    /**
     * 检查当前层级是否为区县级
     *
     * @return 如果是区县级返回true，否则返回false
     */
    public boolean isDistrict() {
        return this == DISTRICT;
    }
    
    /**
     * 检查当前层级是否大于等于指定层级
     *
     * @param other 要比较的层级
     * @return 如果当前层级大于等于指定层级返回true，否则返回false
     */
    public boolean isLevelGte(AreaLevel other) {
        return this.code >= other.code;
    }
    
    /**
     * 检查当前层级是否大于等于指定层级代码
     *
     * @param levelCode 要比较的层级代码
     * @return 如果当前层级大于等于指定层级返回true，否则返回false
     */
    public boolean isLevelGte(Integer levelCode) {
        return levelCode != null && this.code >= levelCode;
    }
    
    @Override
    public String toString() {
        return String.format("AreaLevel{code=%d, name='%s', description='%s'}", 
                code, name, description);
    }
}